package com.bckj.freshnow.order.trade.execution;

import com.bckj.fastboot.core.lang.exception.BusinessException;
import com.bckj.fastboot.core.execution.Execution;
import com.bckj.fastboot.core.execution.ExecutionContext;
import com.bckj.freshnow.order.entity.TradeItem;
import com.bckj.freshnow.order.trade.fsm.TradeOrderContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 库存扣减
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class StockDecreaseExecution implements Execution {

    private final StringRedisTemplate stringRedisTemplate;

    @Override
    public void execute(ExecutionContext context) {
        TradeOrderContext ctx = (TradeOrderContext) context;
        List<TradeItem> items = ctx.getParentOrder().getOrderList().stream().flatMap(tradeItem -> tradeItem.getItemList().stream()).toList();
        List<TradeItem> successfulItems = new ArrayList<>();
        boolean success = true;
        for (TradeItem item : items) {
            boolean r = decreaseStock(item.getSkuCode(), item.getQuantity());
            if (r) {
                successfulItems.add(item);
            } else {
                success = false;
                break;
            }
        }
        if (!success) {
            successfulItems.forEach(item -> increaseStock(item.getSkuCode(), item.getQuantity()));
            throw new BusinessException("库存不足");
        }
        //库存扣减记录
        try {
            //扣减实际库存

            ctx.setSuccessfulItems(successfulItems);
        } catch (Exception e) {
            log.error("扣减实际库存失败，msg=" + e.getMessage(), e);
            //回滚库存
            successfulItems.forEach(item -> increaseStock(item.getSkuCode(), item.getQuantity()));
            //结束执行
            throw e;
        }
    }

    public boolean decreaseStock(String skuCode, Integer num) {
        try {
            List<Object> result = stringRedisTemplate.executePipelined((RedisCallback<Object>) connection -> {
                return null;
            });
            return true;
        } catch (Exception e) {
            log.error("Redis库存扣减失败，msg=" + e.getMessage(), e);
            return false;
        }
    }

    public void increaseStock(String skuCode, Integer num) {
        try {
            List<Object> result = stringRedisTemplate.executePipelined((RedisCallback<Object>) connection -> {
                return null;
            });
        } catch (Exception e) {
            log.error("Redis库存扣减回滚失败，msg=" + e.getMessage(), e);
        }
    }

    @Override
    public void rollback(ExecutionContext context) {
        TradeOrderContext ctx = (TradeOrderContext) context;
        //异常回滚
        if (ctx.getSuccessfulItems() != null) {
            ctx.getSuccessfulItems().forEach(item -> increaseStock(item.getSkuCode(), item.getQuantity()));
        }
    }
}